/*
 * Copyright (c) 2023 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef EGL_CORE_H
#define EGL_CORE_H

#include "glm/glm.hpp"
#include "loader.h"
#include "program.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>
#include "manipulator.h"

#include <thread>
#include <future>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <atomic>



struct GeometryHandler{
    std::shared_ptr<Geometry>geometry;
    glm::vec4 color;
    GLuint vao;
    GLuint vbo;
    GLuint vao_Soma;
    GLuint vbo_Soma;
    bool selected=false;
};
using Callback = std::function<void(std::shared_ptr<Geometry>,const char*)>;

class EGLCore {
public:
    explicit EGLCore(){};
    ~EGLCore() {}
    bool EglContextInit(void *window, int width, int height);
    bool CreateEnvironment();
    void Draw();
    void SetSpecies(const char* species);
    void LoadObj(const char *path);
//    void AddNeuron(const char* sampleid,const char* neuronname,const char* path);
    void removeNeuron(const char* sampleid,const char* neuronname,const char* path);
    void selectNeuron(const char* sampleid,const char* neuronname,const char* path);
    void SetManipulator(std::shared_ptr<Manipulator> manipulator);
    void Release();
    void addEvent(std::shared_ptr<Event>event);
    void DestroyPreviousSurface();
    bool Resize(int newWidth, int newHeight);
    void UpdateSize(int width, int height) ;
//    void loaderThread(const char*path,Callback);
    void loaderCallback(std::shared_ptr<Geometry>neuron,const char*color,const char*path);
private:
    GLint PrepareDraw();
    bool ExecuteDraw( const GLfloat *color);
    bool FinishDraw();

private:
    EGLNativeWindowType m_eglWindow;
    EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
    EGLConfig m_eglConfig = EGL_NO_CONFIG_KHR;
    EGLSurface m_eglSurface = EGL_NO_SURFACE;
    EGLContext m_eglContext = EGL_NO_CONTEXT;
    std::shared_ptr<Program> m_Program;
    std::shared_ptr<Program> m_NeuronProgram;
    std::shared_ptr<Program> m_SomaProgram;
    std::shared_ptr<Geometry> m_Geometry;
    std::map<std::string,GeometryHandler> m_NeuronGeo;
    std::shared_ptr<Manipulator>m_Manipulator;
    std::string m_Species="monkey";
    bool m_selectMode=false;
    bool m_flag = false;
    int m_width;
    int m_height;
    GLfloat m_widthPercent;
    GLuint vbo[2] = {0};
    GLuint vao = 0;
    glm::mat4 model = glm::mat4(1.f);
    glm::mat4 view = glm::mat4(1.f);
    glm::mat4 projection = glm::mat4(1.0f);
    float m_near=0.1f;
    float m_far=1000.0f;
    
    // 全局数据结构：用于存储待执行的主线程回调
    std::queue<std::function<void()>> mainThreadCallbacks;
    std::mutex mtx;
    std::condition_variable cv;
    std::atomic<bool> shouldExit{false}; // 退出标志
    // 主线程事件循环（需在主线程提前启动）
    void MainThreadLoop();
};
#endif
